package com.example.config;

import com.example.service.MyUserDetailService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig  {
    private final MyUserDetailService myUserDetailService;
    @Autowired
    private DataSource dataSource;

    @Autowired
    public SecurityConfig(MyUserDetailService myUserDetailService) {
        this.myUserDetailService = myUserDetailService;
    }

//    自定义记住我实现：PersistentTokenBasedRememberMeServices
//    @Bean
//    public RememberMeServices myRememberMeServices() {
//        方法1.2 使用数据库存储令牌token(似乎不可行，运行代码会报错)
//        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
////        jdbcTokenRepository.setCreateTableOnStartup(false);  // 这种方式登录时，需要手动将源代码中的代码进行编辑，创建sql语句
//        jdbcTokenRepository.setDataSource(dataSource);
//        return new PersistentTokenBasedRememberMeServices(UUID.randomUUID().toString(), myUserDetailService, jdbcTokenRepository);

//       方法1.1 使用内存中的令牌存储token
//        return new PersistentTokenBasedRememberMeServices(UUID.randomUUID().toString(), myUserDetailService, new InMemoryTokenRepositoryImpl());
//    }

    //    自动注入：不知道为什么使用这种方式注入userDetailsService，则自动登录会失败
    @Autowired
    public void initialized(AuthenticationManagerBuilder builder) throws Exception {
        builder.userDetailsService(myUserDetailService);

//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        UserDetails user = User.withUsername("root").password("{noop}123").roles("admin").build();
//        inMemoryUserDetailsManager.createUser(user);

//        builder.userDetailsService(inMemoryUserDetailsManager);
    }

//    自定义数据库内容
//    @Bean
//    public UserDetailsService myUserDetailsService() {
//        UserDetails user = User.withUsername("root").password("{noop}123").roles("admin").build();
//        return new InMemoryUserDetailsManager(user);

//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        UserDetails user = User.withUsername("root").password("{noop}123").roles("admin").build();
//        inMemoryUserDetailsManager.createUser(user);
//        return inMemoryUserDetailsManager;
//    }

    //        方法2、持久化令牌存储到数据库中
    @Bean
    public PersistentTokenRepository myPersistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setCreateTableOnStartup(false);  //第一次登录时设置为true，之后需要手动设置为false
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> {
                    authorizationManagerRequestMatcherRegistry.anyRequest().authenticated();
                })
                .formLogin(formLogin -> {
                })
                .rememberMe(
                        httpSecurityRememberMeConfigurer -> {
                    httpSecurityRememberMeConfigurer
//                            .key("remember-me")
//                            .rememberMeServices(myRememberMeServices());  // 方法一：将token存储到内存中进行持久化
//                            .alwaysRemember(true)   // 在RememberMeService.loginSuccess中进行登录时，会判断是否开启了记住我选项
                            .userDetailsService(myUserDetailService) // myPersistentTokenRepository()
                            .tokenRepository(myPersistentTokenRepository())
//                            .tokenRepository(new JdbcTokenRepositoryImpl())  // 方法二：将token存储到数据库中进行持久化，同时需要使用userDetailsService
//                            .rememberMeParameter("remember-me")  // 用于接收请求中的哪一个参数，作为开启记住我选项的参数
                            .tokenValiditySeconds(86400); // 有效时间（默认为14天，这里设置为）
                })
                .csrf(httpSecurityCsrfConfigurer -> {
                    httpSecurityCsrfConfigurer.disable();
                }).build();
    }
}
